using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml;
namespace Net35.Xrm.Sdk.Linq
{
	internal static class PagingCookieHelper
	{
		public static object[] ToContinuationToken(string pagingCookie, int pageNumber)
		{
			return PagingCookieHelper.Deserialize(pagingCookie, pageNumber).ToArray();
		}
		public static string ToPagingCookie(object[] continuationToken, out int pageNumber)
		{
			return PagingCookieHelper.Serialize(continuationToken, out pageNumber);
		}
		private static List<object> Deserialize(string pagingCookie, int pageNumber)
		{
			ClientExceptionHelper.ThrowIfNegative(pageNumber, "pageNumber");
			List<object> list = new List<object>();
			try
			{
				using (System.Xml.XmlReader xmlReader = PagingCookieHelper.CreateXmlReader(pagingCookie))
				{
					xmlReader.Read();
					list.Add(pageNumber);
					string attribute = xmlReader.GetAttribute("parentEntityId");
					if (!string.IsNullOrEmpty(attribute))
					{
						list.Add(new Guid(attribute));
						string attribute2 = xmlReader.GetAttribute("parentAttributeName");
						ClientExceptionHelper.ThrowIfNullOrEmpty(attribute2, "parentAttributeName");
						list.Add(attribute2);
						int num = -1;
						if (int.TryParse(xmlReader.GetAttribute("parentEntityObjectTypeCode"), out num))
						{
							list.Add(num);
						}
						else
						{
							ClientExceptionHelper.ThrowIfNegative(num, "parentOtc");
						}
					}
					while (xmlReader.Read())
					{
						if (xmlReader.NodeType != System.Xml.XmlNodeType.EndElement)
						{
							string name = xmlReader.Name;
							ClientExceptionHelper.ThrowIfNullOrEmpty(name, "field");
							list.Add(name);
							if (xmlReader.AttributeCount != 2)
							{
								throw new NotSupportedException("Malformed XML Passed to in the Paging Cookie. We expect at most two attributes (first/firstNull and last/lastNull)");
							}
							string attribute3 = xmlReader.GetAttribute("last");
							if (attribute3 == null)
							{
								if (xmlReader.GetAttribute("lastnull") == null)
								{
									throw new NotSupportedException("Malformed XML Passed to in the Paging Cookie. Value for attribute last was not specified, and it was not null either.");
								}
								list.Add(null);
							}
							else
							{
								list.Add(attribute3);
							}
							string attribute4 = xmlReader.GetAttribute("first");
							if (attribute4 == null)
							{
								if (xmlReader.GetAttribute("firstnull") == null)
								{
									throw new NotSupportedException("Malformed XML Passed to in the Paging Cookie. Value for attribute first was not specified, and it was not null either.");
								}
								list.Add(null);
							}
							else
							{
								list.Add(attribute4);
							}
						}
					}
				}
			}
			catch (System.Xml.XmlException innerException)
			{
				throw new NotSupportedException("Malformed XML in the Paging Cookie", innerException);
			}
			catch (FormatException innerException2)
			{
				throw new NotSupportedException("Malformed XML in the Paging Cookie", innerException2);
			}
			return list;
		}
		private static string Serialize(object[] pagingElements, out int pageNumber)
		{
			pageNumber = 0;
			if (pagingElements == null || pagingElements.Length == 0)
			{
				return null;
			}
			if (pagingElements.Length % 3 != 1)
			{
				throw new NotSupportedException("Skip token has incorrect length");
			}
			if (pagingElements[0] != null && pagingElements[0].GetType() == typeof(int) && (int)pagingElements[0] >= 0)
			{
				pageNumber = (int)pagingElements[0];
				string result;
				using (StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture))
				{
					using (System.Xml.XmlWriter xmlWriter = PagingCookieHelper.CreateXmlWriter(stringWriter))
					{
						xmlWriter.WriteStartElement("cookie");
						xmlWriter.WriteAttributeString("page", pageNumber.ToString(CultureInfo.InvariantCulture));
						int num = 1;
						if (pagingElements[1] != null && pagingElements[1].GetType() == typeof(Guid) && pagingElements[2] != null && pagingElements[2].GetType() == typeof(string) && pagingElements[3] != null && pagingElements[3].GetType() == typeof(int))
						{
							num = 4;
							xmlWriter.WriteAttributeString("parentEntityId", pagingElements[1].ToString());
							xmlWriter.WriteAttributeString("parentAttributeName", (string)pagingElements[2]);
							xmlWriter.WriteAttributeString("parentEntityObjectTypeCode", pagingElements[3].ToString());
						}
						for (int i = num; i < pagingElements.Length; i += 3)
						{
							string text = (string)pagingElements[i];
							ClientExceptionHelper.ThrowIfNullOrEmpty(text, "attributeName");
							string localName = string.Empty;
							string localName2 = string.Empty;
							string text2 = (string)pagingElements[i + 1];
							string text3 = (string)pagingElements[i + 2];
							xmlWriter.WriteStartElement(text);
							if (text2 != null)
							{
								localName2 = "last";
							}
							else
							{
								localName2 = "lastnull";
								text2 = "1";
							}
							if (text3 != null)
							{
								localName = "first";
							}
							else
							{
								localName = "firstnull";
								text3 = "1";
							}
							xmlWriter.WriteAttributeString(localName2, text2);
							xmlWriter.WriteAttributeString(localName, text3);
							xmlWriter.WriteEndElement();
						}
						xmlWriter.WriteEndElement();
					}
					result = stringWriter.ToString();
				}
				return result;
			}
			throw new NotSupportedException("Skip token has incorrect page value");
		}
		private static System.Xml.XmlWriter CreateXmlWriter(TextWriter textWriter)
		{
			return System.Xml.XmlWriter.Create(textWriter, new System.Xml.XmlWriterSettings
			{
				Encoding = Encoding.UTF8,
				OmitXmlDeclaration = true
			});
		}
		private static System.Xml.XmlReader CreateXmlReader(string xml)
		{
			System.Xml.XmlReaderSettings xmlReaderSettings = new System.Xml.XmlReaderSettings();
			xmlReaderSettings.IgnoreWhitespace = true;
			return System.Xml.XmlReader.Create(new StringReader(xml), xmlReaderSettings);
		}
	}
}
